module sw.page;
/**
 * Xhtmlを派生して枠組を作る
 */
import nazo.xhtml, nazo.date, nazo.http, nazo.string, std.uri, std.stdio, std.process, nazo.file, nazo.license;
import sw.siteconfig, sw.cgiinfo, sw.menuitem, sw.client, sw.utils;
alias std.string.toString toString;

version(Wiki){
import sw.wiki.article;

bool canWrite(SiteConfig* cfg,Article* page){
  return (Client.authority==Client.Authority.Admin&&!cfg.synchronizeURI.length)
       ||(Client.authority!=Client.Authority.Bot&&page.writable);
}

}else{
  alias void Article;
}

class Page(XhtmlVersion ver = XhtmlVersion.XHTML_1_1):Xhtml!(ver){
  static assert(ver == XhtmlVersion.XHTML_1_1 ||
                  ver == XhtmlVersion.XHTML_PLUS_RDFA, "not impl");
  public{
    ///コンストラクタ
    this(SiteConfig* cfg,string content,string title,Article* page=null,string[] scripts=null,d_time modified=0){
      scope(exit)ownerSec.addChild(Escape.text(getAfter(title,'/')),content,"main");
      bool isBot=cast(bool)(Client.authority==Client.Authority.Bot);
      bool isAdmin=cast(bool)(Client.authority==Client.Authority.Admin);
      bool isGuest=cast(bool)(Client.authority==Client.Authority.Guest);
      bool isShowMailAddr = true;
      bool isRDFa = cast(bool)(ver == XhtmlVersion.XHTML_PLUS_RDFA);
      if(isBot)
        isShowMailAddr = false;
      bool canWrite;
      version(Wiki){
        if(page)canWrite = .canWrite(cfg,page);
      }
      this.scripts=scripts;
      this.title=Escape.text(title)~" - "~cfg.siteName;
      CgiInfo cgiInfo=new CgiInfo;
      this.lang=cfg.defaultLanguage;
      string panlist;//パン屑リスト

      version(Wiki){
        if(page){
          getBeforesWithoutLast(Escape.text(page.title),'/',delegate void(string str){
            panlist~="<li><a href=\""~genURI(cfg, str)~"\">"~str~"</a></li>\n";
          });
          if(panlist.length)panlist="\n<ol class=\"hierarchy\">\n"~panlist~"</ol>";
        }
      }

      this.ownerSec.initialize(cfg.siteName,"<p>"~cfg.siteDescription~"</p>"~panlist);
      if(cfg.manager){
        metas.length=2;
        metas[1].name="manager";
        metas[1].content=cfg.manager;
      }else metas.length=1;
      metas[0].name="generator";
      enum invariant(string) s = cgiInfo.name()~" "~cgiInfo.ver();
      metas[0].content=s;

      this.header=cfg.header ~ "<p id=\"userinfo\">ようこそ "~Client.getName(cfg)~"さん。</p>\n";
      if(cfg.synchronizeURI!="")
        this.header~="<p id=\"msg\">このページは<a href=\""~Escape.text(getOriginalUri(cfg))~"\">上流</a>のミラーです。</p>\n";///Bugs: ミラーした日付が必要。
      else
        if(page)
            this.header~="<p id=\"msg\">このページは編集"~(canWrite?"可能です":"できません")~"。</p>\n";

      version(Wiki){
        this.pi="<?xml-stylesheet type=\"" /*"application/xml"*/ "text/xsl"/*hack for MSXML*/ "\" href=\""~genURI(cfg, "MenuBar")~genURISep(cfg)~"mode=wiki:setmenu\"?>\n";
      }

      uint i3;
      if(cfg.mailAddr.length && isShowMailAddr)i3++;
      if(cfg.cascadingStyleSheet)i3++;
      if(cfg.favIcon)i3++;
      links.length=3+i3;
      i3=0;
      if(cfg.mailAddr.length && isShowMailAddr)
        links[i3++]=newLink("made","mailto:"~cfg.mailAddr,"rev");
      if(cfg.cascadingStyleSheet)
        links[i3++]=newLink("stylesheet",Http.basePath~cfg.cascadingStyleSheet,"rel","text/css");
      if(cfg.favIcon)
        links[i3++]=newLink("icon",Http.basePath~cfg.favIcon,"rel","image/png");
      links[i3++]=newLink("alternate",Http.relPath~"?mode=rss","rel","application/rss+xml","RSS");
      links[i3++]=newLink("help",Http.relPath~"?mode=help");
      links[i3++]=newLink("index",Http.relPath~"?mode=index");

      if(modified)
        metas ~= createDCTERMSMeta("date", "modified", toISO8610String(modified), MetaType.DATETIME);
      metas ~= createDCMeta("language", lang);
      metas ~= createDCMeta("type", "Text");
      if(isRDFa){
        links ~= newResourceLink("dc:publisher", "[_:publisher]");
        if(cfg.mailAddr.length && isShowMailAddr){
          metas ~= createRDFMeta("foaf:name", cfg.manager, "DC.publisher", MetaType.NONE, "[_:publisher]");
          if(cfg.mailAddr && isShowMailAddr)
            metas ~= createRDFMeta("foaf:mbox", "mailto:" ~ cfg.mailAddr, null, MetaType.NONE, "[_:publisher]");
        }
      } else
        metas ~= createDCMeta("publisher", cfg.manager);
      metas ~= createDCMeta("description", "Structure Wikiにより生成されたページです。");

      this.footer=((cfg.mailAddr&&isShowMailAddr)?"<address>管理人: <a href=\""~Http.relPath~"?mode=global:foaf\">"~ cfg.manager ~"</a>(<a href=\"mailto:"~cfg.mailAddr~"\">"~cfg.mailAddr~"</a>)</address>\n":"")~cgiInfo.about()~"\n<p id=\"systeminfo\">現在 "~.toString(cfg.usingSize)~" bytes / "~.toString(cfg.maxSize)~" bytes ("~.toString(cfg.usingSize*100/cfg.maxSize)~"%) 使用中</p>\n";
      CreateMenuItem cmi=CreateMenuItem(cfg);
      this.nl=new Menu;
      if(!page)this.nl.children.length=1;
      else this.nl.children.length=2;
      int n;
      Menu* ml0=&this.nl.children[0];
      uint t;
      if((!isBot||cfg.personalMode)&&!isAdmin)t++;
      if(isAdmin)t++;
      version(Wiki){
        if(!isBot && !(!cfg.canNewPage&&isGuest))t++;
        if(!isBot)t++;
        t+=4;
      }
      ml0.children.length=ml0.children.length+t;
      int i;
      version(Wiki){
        cmi.create!("wiki:index")(&ml0.children[i++]);
        cmi.create!("wiki:menu")(&ml0.children[i++]);
        if(!isBot && !(!cfg.canNewPage&&isGuest)){
          cmi.create!("wiki:new")(&ml0.children[i++]);
        }
        cmi.create!("wiki:list")(&ml0.children[i++]);
        cmi.create!("wiki:recent")(&ml0.children[i++]);
        if(!isBot)
          cmi.create!("wiki:help")(&ml0.children[i++]);
      }
      if((!isBot||cfg.personalMode)&&!isAdmin)cmi.create!("admin:login")(&ml0.children[i++]);
      if(isAdmin)cmi.create!("admin:setting")(&ml0.children[i++]);
      if(!page){
        this.footer ~= cfg.footer;
        return;//もしページじゃないならここで終わり
      }
      version(Wiki){
        Menu* ml1=&this.nl.children[1];
        uint t2;
        if(canWrite)t2++;
        if(isAdmin&&!cfg.synchronizeURI.length)t2++;
        ml1.children.length=ml1.children.length+4+t2;
        int i2;
        cmi.create!("wiki:show")(&ml1.children[i2++],"title",page.title);
        cmi.create!("wiki:source")(&ml1.children[i2++],"title",page.title);
        if(canWrite){
          cmi.create!("wiki:edit")(&ml1.children[i2++],"title",page.title);
        }
        cmi.create!("wiki:diff")(&ml1.children[i2++],"title",page.title);
        cmi.create!("wiki:backuplist")(&ml1.children[i2++],"title",page.title);
        if(isAdmin&&!cfg.synchronizeURI.length){
          if(page.writable)cmi.create!("wiki:freeze",cmi.Method.POST)(&ml1.children[i2++],"title",page.title);
          else cmi.create!("wiki:unfreeze",cmi.Method.POST)(&ml1.children[i2++],"title",page.title);
        }
        auto license = LicenseFactory.create(cfg.wikiDocumentLicense);
        this.footer~=`<p id="license">`~license.descriptionHTML()~`</p>` ~ cfg.footer;
        metas ~= createDCMeta("rights", license.name());
      }
    }
  }
}
